#include "MuWinWindow.h"
 #include "ui_MuWinWindow.h"

#include <QLayout>
#include <QPainter>
// #include <QDesktopWidget>
#include <QScreen>

// #include <QtWinExtras/QtWin>
#include <dwmapi.h>

#include "MuWinTitlebar.h"

#pragma comment (lib, "user32.lib")

#ifndef GET_X_LPARAM
#define GET_X_LPARAM(lParam)    ((int)(short)LOWORD(lParam))
#endif
#ifndef GET_Y_LPARAM
#define GET_Y_LPARAM(lParam)    ((int)(short)HIWORD(lParam))
#endif

MuWinWindow::MuWinWindow(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MuWinWindow)
{
    ui->setupUi(this);
    setWindowFlags(Qt::FramelessWindowHint);

    HWND hwnd = reinterpret_cast<HWND>(this->winId());
    DWORD style = GetWindowLong(hwnd, GWL_STYLE);
    SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_CAPTION);

    // bool enabled = QtWin::isCompositionEnabled();
    // if (enabled) {
    //     HWND hwnd = (HWND)this->winId();
    //     DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
    //     ::SetWindowLong(hwnd, GWL_STYLE, style | WS_THICKFRAME | WS_CAPTION | WS_BORDER);
    //     QtWin::extendFrameIntoClientArea(this, 1, 1, 1, 1);
    // }
    this->installEventFilter(ui->titlebar);

    connect(ui->titlebar, &MuWinTitlebar::ShowMinimized, this, &MuWinWindow::showMinimized);
    connect(ui->titlebar, &MuWinTitlebar::ShowMaximized, this, &MuWinWindow::showMaximized);
    connect(ui->titlebar, &MuWinTitlebar::ShowRestoreSize, this, &MuWinWindow::showNormal);
    connect(ui->titlebar, &MuWinTitlebar::Close, this, &MuWinWindow::close);
}

MuWinWindow::~MuWinWindow()
{
}

bool MuWinWindow::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
{
#ifdef Q_OS_WIN
    if (eventType != "windows_generic_MSG")
        return false;

    MSG* msg = static_cast<MSG*>(message);

    QWidget* widget = QWidget::find(reinterpret_cast<WId>(msg->hwnd));
    if (!widget)
        return false;

    switch (msg->message) {
    case WM_NCCALCSIZE: {
        *result = 0;
        return true;
    }

    case WM_NCHITTEST: {
        int x = GET_X_LPARAM(msg->lParam);
        int y = GET_Y_LPARAM(msg->lParam);

        auto factor = this->screen()->devicePixelRatio();
        x = x / factor;
        y = y / factor;
        QPoint pt = mapFromGlobal(QPoint(x, y));
        
        auto region = ui->titlebar->GetProperRegion();
        if (region.contains(pt))
        {
            *result = HTCAPTION;
        }
        else
        {
            *result = calculateBorder(pt);
            if (*result == HTCLIENT) {
                QWidget* tempWidget = this->childAt(pt.x(), pt.y());
                if (tempWidget == NULL) {
                    *result = HTCAPTION;
                }
            }
        }

        return true;
    }
    case WM_GETMINMAXINFO: {
        if (::IsZoomed(msg->hwnd)) {
            isMaximized_ = true;
            RECT frame = { 0, 0, 0, 0 };
            AdjustWindowRectEx(&frame, WS_OVERLAPPEDWINDOW, FALSE, 0);
            frame.left = abs(frame.left);
            frame.top = abs(frame.bottom);
            widget->setContentsMargins(frame.left, frame.top, frame.right, frame.bottom);
        }
        else {
            widget->setContentsMargins(0, 0, 0, 0);
            isMaximized_ = false;
        }

        //*result = ::DefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam);
        return true;
    }
    break;

    default:
        break;
    }

#endif

    return QWidget::nativeEvent(eventType, message, result);
}

LRESULT MuWinWindow::calculateBorder(const QPoint &pt)
{
    if (::IsZoomed((HWND)this->winId())) {
        return HTCLIENT;
    }
    int borderSize = 4;
    int cx = this->size().width();
    int cy = this->size().height();

    QRect rectTopLeft(0, 0, borderSize, borderSize);
    if (rectTopLeft.contains(pt)) {
        return HTTOPLEFT;
    }

    QRect rectLeft(0, borderSize, borderSize, cy - borderSize * 2);
    if (rectLeft.contains(pt)) {
        return HTLEFT;
    }

    QRect rectTopRight(cx - borderSize, 0, borderSize, borderSize);
    if (rectTopRight.contains(pt)) {
        return HTTOPRIGHT;
    }

    QRect rectRight(cx - borderSize, borderSize, borderSize, cy - borderSize * 2);
    if (rectRight.contains(pt)) {
        return HTRIGHT;
    }

    QRect rectTop(borderSize, 0, cx - borderSize * 2, borderSize);
    if (rectTop.contains(pt)) {
        return HTTOP;
    }

    QRect rectBottomLeft(0, cy - borderSize, borderSize, borderSize);
    if (rectBottomLeft.contains(pt)) {
        return HTBOTTOMLEFT;
    }

    QRect rectBottomRight(cx - borderSize, cy - borderSize, borderSize, borderSize);
    if (rectBottomRight.contains(pt)) {
        return HTBOTTOMRIGHT;
    }

    QRect rectBottom(borderSize, cy - borderSize, cx - borderSize * 2, borderSize);
    if (rectBottom.contains(pt)) {
        return HTBOTTOM;
    }

    return HTCLIENT;
}

